option (USE_INTERNAL_CCTZ_LIBRARY "Use internal cctz library" ${NOT_UNBUNDLED})

if (NOT USE_INTERNAL_CCTZ_LIBRARY)
    find_library (LIBRARY_CCTZ cctz)
    find_path (INCLUDE_CCTZ NAMES cctz/civil_time.h)

    if (LIBRARY_CCTZ AND INCLUDE_CCTZ)
        set (EXTERNAL_CCTZ_LIBRARY_FOUND 1)

        set(CMAKE_REQUIRED_LIBRARIES ${LIBRARY_CCTZ})
        set(CMAKE_REQUIRED_INCLUDES ${INCLUDE_CCTZ})
        check_cxx_source_compiles(
            "
            #include <cctz/civil_time.h>
            int main() {
                cctz::civil_day date;
            }
            "
            EXTERNAL_CCTZ_LIBRARY_WORKS
        )

        if (NOT EXTERNAL_CCTZ_LIBRARY_WORKS)
            message (${RECONFIGURE_MESSAGE_LEVEL} "External cctz is not working: ${LIBRARY_CCTZ} ${INCLUDE_CCTZ}")
        else()
            add_library (cctz UNKNOWN IMPORTED)
            set_property (TARGET cctz PROPERTY IMPORTED_LOCATION ${LIBRARY_CCTZ})
            set_property (TARGET cctz PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INCLUDE_CCTZ})
        endif()
        
        set(SYSTEM_STORAGE_TZ_FILE "${CMAKE_BINARY_DIR}/src/Storages/System/StorageSystemTimeZones.generated.cpp")
        file(REMOVE ${SYSTEM_STORAGE_TZ_FILE})
        file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "// autogenerated by ClickHouse/contrib/cctz-cmake/CMakeLists.txt\n")
        file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "const char * auto_time_zones[] {nullptr};\n" )

    else()
        set (EXTERNAL_CCTZ_LIBRARY_FOUND 0)
        message (${RECONFIGURE_MESSAGE_LEVEL} "Can't find system cctz")
    endif()
endif()

if (NOT EXTERNAL_CCTZ_LIBRARY_FOUND OR NOT EXTERNAL_CCTZ_LIBRARY_WORKS)
    set(USE_INTERNAL_CCTZ_LIBRARY 1)
    set(LIBRARY_DIR ${ClickHouse_SOURCE_DIR}/contrib/cctz)

    set (SRCS
        ${LIBRARY_DIR}/src/civil_time_detail.cc
        ${LIBRARY_DIR}/src/time_zone_fixed.cc
        ${LIBRARY_DIR}/src/time_zone_format.cc
        ${LIBRARY_DIR}/src/time_zone_if.cc
        ${LIBRARY_DIR}/src/time_zone_impl.cc
        ${LIBRARY_DIR}/src/time_zone_info.cc
        ${LIBRARY_DIR}/src/time_zone_libc.cc
        ${LIBRARY_DIR}/src/time_zone_lookup.cc
        ${LIBRARY_DIR}/src/time_zone_posix.cc
        ${LIBRARY_DIR}/src/zone_info_source.cc
    )

    add_library (cctz ${SRCS})
    target_include_directories (cctz PUBLIC ${LIBRARY_DIR}/include)

    if (OS_FREEBSD)
        # yes, need linux, because bsd check inside linux in time_zone_libc.cc:24
        target_compile_definitions (cctz PRIVATE __USE_BSD linux _XOPEN_SOURCE=600)
    endif ()

    # Related to time_zones table:
    # StorageSystemTimeZones.generated.cpp is autogenerated each time during a build
    # data in this file will be used to populate the system.time_zones table, this is specific to OS_LINUX
    # as the library that's built using embedded tzdata is also specific to OS_LINUX
    set(SYSTEM_STORAGE_TZ_FILE "${CMAKE_BINARY_DIR}/src/Storages/System/StorageSystemTimeZones.generated.cpp")
    # remove existing copies so that its generated fresh on each build.
    file(REMOVE ${SYSTEM_STORAGE_TZ_FILE})
    # Build a libray with embedded tzdata
    if (OS_LINUX)
        # get the list of timezones from tzdata shipped with cctz
        set(TZDIR ${LIBRARY_DIR}/testdata/zoneinfo)
        file(STRINGS ${LIBRARY_DIR}/testdata/version TZDATA_VERSION)
        set_property(GLOBAL PROPERTY TZDATA_VERSION_PROP "${TZDATA_VERSION}")
        message(STATUS "Packaging with tzdata version: ${TZDATA_VERSION}")

        set(TZ_OBJS)

        # each file in that dir (except of tab and localtime) store the info about timezone
        execute_process(COMMAND
            bash -c "cd ${TZDIR} && find * -type f -and ! -name '*.tab' -and ! -name 'localtime' | sort | paste -sd ';'"
            OUTPUT_STRIP_TRAILING_WHITESPACE
            OUTPUT_VARIABLE TIMEZONES)

        file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "// autogenerated by ClickHouse/contrib/cctz-cmake/CMakeLists.txt\n")
        file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "const char * auto_time_zones[] {\n" )

        foreach(TIMEZONE ${TIMEZONES})
            file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "    \"${TIMEZONE}\",\n")
            string(REPLACE "/" "_" TIMEZONE_ID ${TIMEZONE})
            string(REPLACE "+" "_PLUS_" TIMEZONE_ID ${TIMEZONE_ID})
            set(TZ_OBJ ${TIMEZONE_ID}.o)
            set(TZ_OBJS ${TZ_OBJS} ${TZ_OBJ})

            # https://stackoverflow.com/questions/14776463/compile-and-add-an-object-file-from-a-binary-with-cmake
            add_custom_command(OUTPUT ${TZ_OBJ}
                COMMAND cp ${TZDIR}/${TIMEZONE} ${CMAKE_CURRENT_BINARY_DIR}/${TIMEZONE_ID}
                COMMAND cd ${CMAKE_CURRENT_BINARY_DIR} && ${OBJCOPY_PATH} -I binary ${OBJCOPY_ARCH_OPTIONS}
                            --rename-section .data=.rodata,alloc,load,readonly,data,contents ${TIMEZONE_ID} ${TZ_OBJ}
                COMMAND rm ${CMAKE_CURRENT_BINARY_DIR}/${TIMEZONE_ID})

            set_source_files_properties(${TZ_OBJ} PROPERTIES EXTERNAL_OBJECT true GENERATED true)
        endforeach(TIMEZONE)

        file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "    nullptr};\n")

        add_library(tzdata STATIC ${TZ_OBJS})
        set_target_properties(tzdata PROPERTIES LINKER_LANGUAGE C)
        # whole-archive prevents symbols from being discarded for unknown reason
        # CMake can shuffle each of target_link_libraries arguments with other
        # libraries in linker command. To avoid this we hardcode whole-archive
        # library into single string.
        add_dependencies(cctz tzdata)
        target_link_libraries(cctz INTERFACE "-Wl,${WHOLE_ARCHIVE} $<TARGET_FILE:tzdata> -Wl,${NO_WHOLE_ARCHIVE}")
    else ()
        file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "// autogenerated by ClickHouse/contrib/cctz-cmake/CMakeLists.txt\n")
        file(APPEND ${SYSTEM_STORAGE_TZ_FILE} "const char * auto_time_zones[] {nullptr};\n" )
    endif ()
endif ()

message (STATUS "Using cctz")
